home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Online / Apache / cgi-bin / rx-gate.c < prev    next >
C/C++ Source or Header  |  1997-06-11  |  7KB  |  266 lines

  1. /*    `
  2.  * gcc -o rx-gate rx-gate.c -O
  3.  *
  4.  * CGI Gateway to Rexx scripts. Due to the way Rexx scripts work, they don't
  5.  * inherit local variables from the httpd that spawned them. This C program
  6.  * does inhereit them, and makes the available via a Rexx port. It launches
  7.  * the script with the cgi port as the scripts default port.
  8.  *
  9.  * Invoke this with the script name to use.
  10.  *
  11.  * Copyright © 1994, Mike Meyer, modified by Jeff Shepherd to use with Apache
  12.  */
  13.  
  14. #include <string.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17.  
  18. #include <exec/types.h>
  19. #include <dos/dos.h>
  20. #include <rexx/storage.h>
  21. #include <proto/exec.h>
  22. #include <proto/dos.h>
  23. #include <proto/rexxsyslib.h>
  24.  
  25. #define MAXVAR 256
  26. #define STDOUT 1
  27.  
  28. struct RxsLib *RexxSysBase ;
  29. struct MsgPort *port ;
  30.  
  31. #define dead(x) return corpse(x,NULL,NULL)
  32. int corpse(char *, char *, char *) ;
  33.  
  34. char line[1024];
  35. int main(int argc, char **argv) {
  36.     char *value, command[MAXVAR], port_name[20];
  37.     char error_msg[MAXVAR];
  38.     char tempstdoutname[24], tempstdinname[29];
  39.     char *com;
  40.     BPTR tempstdout, oldstdout, tempstdin, oldstdin;
  41.     FILE *fi;
  42.     char *cmdline = NULL;
  43.     int len;
  44.     struct RexxMsg  *msg ;
  45.     struct MsgPort *rexxport ;
  46.     int i;
  47.     int exit_status = 0;
  48.  
  49.     RexxSysBase = NULL ;
  50.     port = NULL ;
  51.  
  52. #ifdef DEBUG
  53.     puts("Content-type: text/plain\n");
  54. #endif
  55.  
  56.     /* Get the Rexx library */
  57.     if ((RexxSysBase = (struct RxsLib *)OpenLibrary("rexxsyslib.library", 0)) == NULL)
  58.         dead("Can't open rexx library") ;
  59.  
  60.     /* Get a message port */
  61.     sprintf(port_name, "CGI-PORT-%lx", (ULONG)FindTask(NULL));
  62.  
  63.     /* temporary files for stdin and stdout */
  64.     sprintf(tempstdoutname, "t:CGI-PORT-%lx", (ULONG)FindTask(NULL));
  65.     sprintf(tempstdinname, "t:CGI-PORT-%lx-stdin", (ULONG)FindTask(NULL));
  66.     Forbid() ;
  67.     if (!FindPort(port_name)) port = CreatePort(port_name, 0) ;
  68.     Permit() ;
  69.     if (port == NULL)       /* BAD news */
  70.         dead("Can't create Rexx port") ;
  71.  
  72.     /* Build the message that starts things rolling */
  73.     if ((msg = CreateRexxMsg(port, NULL, port->mp_Node.ln_Name)) == NULL)
  74.         dead("Can't create rexx message") ;
  75.  
  76.     /* Make one big command line to pass to the arexx script */
  77.     for (len  = 1, i = 0; i < argc; i++) {
  78. #ifdef DEBUG
  79.     printf("Argv %d = %s\n", i, argv[i]);
  80. #endif
  81.     len += strlen(argv[i]) + 1;
  82.     }
  83.  
  84.     cmdline = malloc(len);
  85.     strcpy (cmdline, argv[0]);
  86.     for (i = 1; i < argc; i++) {
  87.     strcat(cmdline, " ");
  88.     strcat(cmdline, argv[i]);
  89.     }
  90.  
  91. #ifdef DEBUG
  92.     printf("Cmdline is %s\n", cmdline);
  93. #endif
  94.     msg->rm_Args[0] = cmdline;
  95.     if (!FillRexxMsg(msg, 1, 0)) {
  96.         free(cmdline);
  97.         DeleteRexxMsg(msg) ;
  98.         dead("Can't create rexx arguments") ;
  99.     }
  100.     free(cmdline);
  101.     msg->rm_Action = RXCOMM;
  102.  
  103.     /* Since I was started by exec() my Output() is bogus but stdout
  104.      * is the socket, I will set my Output() to a temp file
  105.      * Also redirect stdin to a temp file since Input() is also the socket
  106.      */
  107.      fi = fopen(tempstdinname, "w");
  108.      if (fi) {
  109.     while(fgets(line, 1024, stdin))
  110.         fprintf(fi,"%s",line);
  111.     fclose(fi);
  112.     }
  113.  
  114.     tempstdout = Open(tempstdoutname, MODE_NEWFILE);
  115.     tempstdin = Open(tempstdinname, MODE_OLDFILE);
  116.     oldstdout = SelectOutput(tempstdout);
  117.     oldstdin = SelectInput(tempstdin);
  118.  
  119.     /* Go! */
  120.     Forbid();
  121.     if ((rexxport = FindPort(RXSDIR)))
  122.         PutMsg(rexxport, (struct Message *) msg) ;
  123.     Permit();
  124.  
  125.     if (!rexxport) {
  126.     ClearRexxMsg(msg, 1);
  127.     DeleteRexxMsg(msg);
  128.     SelectOutput(oldstdout);
  129.     SelectOutput(oldstdin);
  130.     Close(tempstdout);
  131.     Close(tempstdin);
  132.     remove(tempstdinname);
  133.     remove(tempstdoutname);
  134.     dead("Can't find rexx port");
  135.     }
  136.  
  137.     /* must redirect Arexx output to file because stdin is a socket */
  138.     /* Ok, now we just wait for the message to come back... */
  139.     for (;;) {
  140.     WaitPort(port) ;
  141.     msg = (struct RexxMsg *) GetMsg(port) ;
  142.     if (msg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG) break ;
  143.  
  144.     /* That wasn't the reply, so we have a command */
  145.     strcpy(command, msg->rm_Args[0]) ;
  146. #ifdef DEBUG
  147.     printf("Command %s\n", command);
  148. #endif
  149.     com = strtok(command, " \t") ;
  150.  
  151.     /* if it was getvar, handle it */
  152.     if (!stricmp(com , "getvar")) {
  153.         char *tok;
  154.         /* Doing getvar */
  155.         tok = strtok(NULL, " \t");
  156.         if ((value = getenv(tok)) == NULL)
  157.         value = "";
  158.         msg->rm_Result1 = 0 ;
  159.         if (!(msg->rm_Action & RXFF_RESULT))
  160.         msg->rm_Result2 = strlen(value) ;
  161.         else msg->rm_Result2 =
  162.         (LONG) CreateArgstring(value,
  163.         strlen(value)) ;
  164.     }
  165.     else {
  166. #ifdef DEBUG
  167.         printf("Bad token %s\n", com);
  168. #endif
  169.         msg->rm_Result1 = 10 ;
  170.         msg->rm_Result2 = 11 ;
  171.         exit_status = 1;
  172.         sprintf(error_msg, "Rexx error: #%ld", msg->rm_Result2) ;
  173.     }
  174.     ReplyMsg((struct Message *) msg) ;
  175.     }
  176.  
  177.     ClearRexxMsg(msg, 1) ;
  178.     DeleteRexxMsg(msg) ;
  179.     Close(tempstdout);
  180.     Close(tempstdin);
  181.  
  182.     /* echo the contents of the file to the socket */
  183.     SelectOutput(oldstdout);
  184.     SelectInput(oldstdin);
  185.  
  186.     /* only print the contents of the file if the exit status is 0 */
  187.     if (exit_status == 0) {
  188.     fi = fopen(tempstdoutname, "r");
  189.     if (fi) {
  190.         while(fgets(line, 1024, fi))
  191.         printf("%s", line);
  192.         fclose(fi);
  193.     }
  194.     remove(tempstdinname);
  195.     remove(tempstdoutname);
  196.     dead(NULL);
  197.     }
  198.     else
  199.     return corpse(error_msg, tempstdinname, tempstdoutname);
  200. }
  201.  
  202. int
  203. corpse(char *mesg, char *stdinfi, char *stdoutfi) {
  204.     char *program_name ;
  205.  
  206. #ifdef DEBUG
  207.     printf("mesg is %s, stdinfi is %s, stdoutfi is %s\n", mesg, stdinfi, stdoutfi);
  208. #endif
  209.     if (mesg) {
  210.     if ((program_name = getenv("SERVER_NAME")) == NULL)
  211.         program_name = "NOT CONFIGURED" ;
  212.     printf("Content-type: text/html\n\n"
  213.         "<HTML><HEAD><TITLE>Rexx Gateway error</TITLE></HEAD><BODY>\n"
  214.         "<h1>%s</h1>\nPlease contact the %s server admin.\n",
  215.         mesg, program_name) ;
  216.     }
  217.  
  218.     if (stdinfi) {
  219.     char line[1024];
  220.     FILE *fi;
  221.  
  222.     fi = fopen(stdinfi, "r");
  223.     if (fi) {
  224.         if (!mesg)
  225.         puts("Content-type: text/html\n");
  226.  
  227.         puts("<HR><h1>STDIN</h1>");
  228.         puts("<CODE>");
  229.         while(fgets(line,1024,fi))
  230.         printf("%s",line);
  231.         fclose(fi);
  232.         puts("</CODE>");
  233.     }
  234.     remove(stdinfi);
  235.     }
  236.  
  237.     if (stdoutfi) {
  238.     char line[1024];
  239.     FILE *fi;
  240.  
  241.     fi = fopen(stdoutfi, "r");
  242.     if (fi) {
  243.         puts("<HR><h1>STDOUT</h1>");
  244.         puts("<CODE>");
  245.         while(fgets(line,1024,fi))
  246.         printf("%s",line);
  247.         fclose(fi);
  248.         puts("</CODE>");
  249.     }
  250.     remove(stdoutfi);
  251.     }
  252.  
  253.     if (mesg || stdinfi || stdoutfi)
  254.     puts("</HTML>");
  255.  
  256.     if (port) {
  257.     FreeSignal((long) (port->mp_SigBit)) ;
  258.     RemPort(port) ;
  259.     DeletePort(port) ;
  260.     }
  261.     if (RexxSysBase)
  262.     CloseLibrary((struct Library *)RexxSysBase) ;
  263.  
  264.     return 0 ;
  265. }
  266.